import React, {
    useState, useMemo, useRef, forwardRef, useImperativeHandle, useEffect,
} from "react";
import { current } from "immer";
import {
    Table, Button, Pagination, type TableColumnType, Tag,
    message,
} from 'antd';
import { useAntdResizableHeader } from 'use-antd-resizable-header';
import { ResultEnum } from "@/enums/httpEnum";
import GameAll from './components/GameAll';
import SearchComp from './components/SearchComp';
import ColumnSettingModal from './components/ColumnSettingModal';
import ToolsBar from './components/ToolsBar';
import HoverTooltip from './components/HoverTooltip';
import eventBus from '@/utils/eventBus';

import 'use-antd-resizable-header/dist/style.css';
import './index.less';

export interface ColumnsType extends TableColumnType {
    valueType?: 'text' | 'password' | 'money' | 'digit' | 'date' | 'datetime' | 'dateRange' | 'datetimeRange' | 'time' | 'cascader' | 'number'
        | 'timeRange' | 'textarea' | 'select' | 'checkbox' | 'radio' | 'switch' | 'rate' | 'progress' | 'percent' | 'option' | 'upload' | 'search'
        | 'index' | 'indexBorder' | 'optionButton' | 'moneyRange' | 'checkboxChildren'
        | 'user'; // 接口的类型的
    valueEnum?: any;
    hideSearch?: boolean;
    hideTable?: boolean;
    colIndex?: number;
    onChange?: any;
    minConstraints?: any;
    placeholder?: string;
    options?: any;
    formProps?: any;
    required?: boolean;
    hidden?: boolean;
    initialValue?: any;
    assistant?: any; // 渲染出一个空位占位 可以通过 form.setFieldsValue 设置进去。
}

export interface ToolsType {
    type: 'button' | 'dropdown' | 'switch' | 'selectAndButton';
    text: string;
    compProps?: any;
    onClick?: any;
    onSelect?: any;
    onChange?: any;
    options?: any;
    style?: any;
}

export interface Props {
    tableName: string;
    isShowGameAll?: boolean;
	actionRef?: any;
    formRef?: any;
    columns: ColumnsType[];
    tools?: ToolsType[];
    rowSelection?: any;
    // 请求相关
    request?: any;
    initialState?: any;
    params?: object;
    formatData?: any;
    gameLoad?: any;
}

let timer: any = 0;
const TableComp = forwardRef((props: any, ref) => {
    const {
        tableName, tableClass,
        rowSelection, columns: propsColumns, dataSource: propsDataSource = [],
        toolsRef, colSettingModalRef,
        request, initialState: { autoRequest = true } = {  }, params = {}, formatData: formatDataFunc,
    } = props;

    const fetchRef = useRef(0);
    const [loading, setLoading] = useState(false);
    const [filter, setFilter] = useState({ page: 1, limit: 15, total: 0, time: new Date().getTime() });
    const [columns, setColumns] = useState(propsColumns || []);
    const [tableContentHeight, setTableContentHeight] = useState(0);
    const [dataSource, setDataSource] = useState(propsDataSource || [{key:1}, {key:2}, {key:3}, {key:4}]);
    const { components, resizableColumns, tableWidth } = useAntdResizableHeader({
        columns: useMemo(() => {
            return columns.reduce((init: any, column: any, index: any) => {
                if (!column.hideTable) {
                    const { valueEnum } = column;
                    const newValueEnum = typeof valueEnum === 'function' ? valueEnum() : valueEnum;
                    // const colorArr = ['magenta', 'red', 'volcano', 'orange', 'gold', 'lime', 'green', 'cyan', 'blue', 'geekblue', 'purple'];
                    init.push({
                        ...column,
                        colIndex: index,
                        render: (...args: any) => {
                            if (column.render) {
                                if (newValueEnum && newValueEnum.constructor === Object) {
                                    return column.render(newValueEnum[args[0]].text, args[1], args[2], args[3], newValueEnum);
                                }
                                if (newValueEnum && newValueEnum.constructor === Array) {
                                    const newValueEnumItem = newValueEnum.find((item: any) => item.value == args[0]);
                                    return column.render(newValueEnumItem.label, args[1], args[2], args[3], newValueEnum);
                                }
                                return <HoverTooltip>{column.render(...args)}</HoverTooltip>;
                            } else {
                                if (newValueEnum && newValueEnum.constructor === Object) {
                                    const newValueEnumItem = newValueEnum[args[0]] || {};
                                    if (newValueEnumItem.displayType === 'button') {
                                        return <Button {...(newValueEnumItem.props || {})}>{newValueEnumItem.text || '-'}</Button>;
                                    }
                                    return <Tag color={newValueEnumItem.status}>{newValueEnumItem.text || '-'}</Tag>;
                                }
                                if (newValueEnum && newValueEnum.constructor === Array) {
                                    const newValueEnumItem = newValueEnum.find((item: any) => item.value == args[0]) || {};
                                    if (newValueEnumItem.displayType === 'button') {
                                        return <Button {...(newValueEnumItem.props || {})}>{newValueEnumItem.text}</Button>;
                                    }
                                    return <Tag color={newValueEnumItem.status}>{newValueEnumItem.text || '-'}</Tag>;
                                }
                                if (args[0]) {
                                    if (typeof args[0] === 'object' || typeof args[0] === 'function') {
                                        return <HoverTooltip>{JSON.stringify(args[0])}</HoverTooltip>;
                                    }
                                    return <HoverTooltip>{args[0]}</HoverTooltip>;
                                }
                                return '-';
                            }
                        },
                    });
                }
                return init;
            }, []);
        }, [columns]),
        // 保存拖拽宽度至本地localStorage
        columnsState: {
            persistenceKey: tableName,
            persistenceType: 'localStorage',
        },
    });

    const handleResetWidth = () => {
        localStorage.setItem(tableName, '');
        message.warning(`清除缓存成功！${tableName}一秒后刷新！`);
        setTimeout(() => window.location.reload(), 1000);
    };
    const handleSettingModalOpen = () => {
        colSettingModalRef.current.show();
    };
    const onRowSelectionChange = toolsRef.current.setSelectKeys;
    const fetchDataFunc = async (...args: any) => {
        const formData = {
            ...params,
            ...filter,
            ...(args[1] || {}),
            scheme: undefined, // 这是方案名 不用传过去
            total: undefined, // 这是总条数 不用传过去
            time: undefined, // 切换时间戳 不用传过去
        };
        setLoading(true);
        try {
            const { code, data } = await request(formData);
            if (args[0] !== fetchRef.current) return;
            if (code === ResultEnum.SUCCESS) {
                const newData = data.data || [];
                const formatData = formatDataFunc ? formatDataFunc(newData) : newData;
                setDataSource(formatData);
                setFilter((pre) => ({ ...pre, total: data.total || 0 }))
            }
            setLoading(false);
        } catch (err) {
            setLoading(false);
            console.log(`${tableName}----请求失败`, err);
        }
    };
    const fetchData = (...args: any) => {
        clearTimeout(timer);
        timer = setTimeout(() => {
            fetchRef.current++;
            fetchDataFunc(fetchRef.current, ...args);
        }, 200);
    };
    const onPageChange = (...args: any) => {
        const newFilter = {
            ...filter,
            page: args[0],
            limit: args[1],
            time: new Date().getTime(),
        };
        setFilter(newFilter);
        fetchData(newFilter);
    };

    useEffect(() => setColumns(propsColumns), [propsColumns]);

    useEffect(() => {
        if (autoRequest) fetchData();
        const autoResize = () => {
            setTimeout(() => {
                const containerHeight = (document.querySelector(`.${tableClass}`) as any).offsetHeight;
                const containerFilterHeight = (document.querySelector(`.${tableClass} .table-comp-filter`) as any).offsetHeight;
                setTableContentHeight(
                    containerHeight - (containerFilterHeight) // 动态头
                        - (47 + 48 + 50) // 表头和列配置跟页码
                        - (12) // 边距
                );
            }, 16.666);
            return autoResize;
        };
        const callback = autoResize();
        window.addEventListener('resize', callback, false);
        eventBus.addListener('filterCompResize', callback);
        return () => {
            window.removeEventListener('resize', callback, false);
            eventBus.removeListener('filterCompResize', callback);
        };
    }, []);

    useImperativeHandle(ref, () => ({
        reload: () => {},
        onSearch: (params: any) => {
            const newFilter = {
                total: filter.total,
                limit: filter.limit,
                page: 1,
                time: new Date().getTime(),
                ...(params || {}),
            };
            setFilter(newFilter);
            fetchData(newFilter);
        },
    }));

    return (
        <>
            <div className="table-comp-wrap">
                <div className="table-comp-header">
                    <span className="flex1">{tableName}</span>
                    <div className="handle-btn-wrap">
                        <Button onClick={handleResetWidth}>重置列宽</Button>
                        <Button onClick={handleSettingModalOpen} className="el-button el-tooltip el-button--warning el-button--small">
                            <span>列表配置</span>
                        </Button>
                    </div>
                </div>
                <Table
                    rowKey="key"
                    bordered
                    loading={loading}
                    columns={resizableColumns}
                    components={components}
                    scroll={{ x: tableWidth, y: tableContentHeight }}
                    dataSource={dataSource}
                    pagination={false}
                    rowSelection={rowSelection ? {
                        ...rowSelection,
                        onChange: onRowSelectionChange,
                    } : false}
                />
            </div>

            <div className="table-comp-pagination">
                <span>共{filter.total}条数据</span>
                <Pagination
                    total={filter.total}
                    current={filter.page}
                    pageSize={filter.limit}
                    onChange={onPageChange}
                    showQuickJumper
                    showSizeChanger
                    pageSizeOptions={[10, 15, 20, 50, 100, 200]}
                />
            </div>
        </>
    );
});

TableComp.displayName = 'TableComp';

const Comp = (props: Props) => {
    const tableClassName = `dync-table`; // 后续做动态 防止一个页面多个表格 导致dom获取不准确
    const formRef: any = useRef({ current });
    const actionRef: any = useRef({ current });
    const toolsRef: any = useRef({ current });
    const colSettingModalRef: any = useRef({ current });
    const {
        tableName, isShowGameAll, gameLoad,
        columns = [], tools = [],
    } = props;

    const searchColumns: ColumnsType[] = useMemo(() => {
        return columns.reduce((init: any, column, index) => {
            if (!column.hideSearch && column.valueType) {
                init.push({ ...column, colIndex: index });
            }
            return init;
        }, []);
    }, [columns]);

    const onSearch = (params: any) => {
        actionRef.current?.onSearch(params);
    };

    return (
        <div className={`components-table-demo-resizable-column ${tableClassName}`}>
            <div className="table-comp-filter">
                {/**/}
                { isShowGameAll ? <GameAll gameLoad={gameLoad} /> : '' }
                {/* search */}
                { searchColumns.length ? (
                    <SearchComp
                        formRef={formRef}
                        actionRef={actionRef}
                        tableName={tableName}
                        columns={searchColumns}
                        onSearch={onSearch}
                    />
                ) : '' }
                {/* tools */}
                { tools?.length ? (
                    <ToolsBar
                        formRef={formRef} 
                        actionRef={actionRef}
                        ref={toolsRef}
                        tools={tools}
                    />
                ) : '' }
            </div>
            
            <TableComp
                ref={actionRef}
                toolsRef={toolsRef}
                colSettingModalRef={colSettingModalRef}
                tableClass={tableClassName}
                {...props}
            />

            <ColumnSettingModal
                columns={columns}
                ref={colSettingModalRef}
            />
        </div>
    );
};

export default Comp;